package com.bacga.abctest;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@Scope("prototype")
@Slf4j
@Data
public class HttpScheduler {

    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    /**
     * 完成请求数
     */
    private AtomicInteger finishRequestCount = new AtomicInteger();
    /**
     * 成功请求数
     */
    private AtomicInteger successRequestCount = new AtomicInteger();
    /**
     * 完成所有请求的线程数
     */
    private AtomicInteger finishRequestThreadCount = new AtomicInteger();
    /**
     * 记录总消耗时间
     */
    private Long finishAllUseTime = 0l;
    /**
     * 记录成功率
     */
    private String successRate;
    /**
     * 记录3s请求数
     */
    private Integer localRequestCount = 0;
    /**
     * 记录调用耗时分布状况
     */
    private ConcurrentHashMap<String,String> useTimeGather = new ConcurrentHashMap<>();
    /**
     * 记录所有调用时间
     */
    private List<Long> useTimeList = new CopyOnWriteArrayList<>();
    /**
     * 标记scheduler是否被锁定
     */
    private volatile boolean lock = false;

    private int threadCount;
    private int requestCount;
    private String requestUrl;

    public HttpScheduler() {

    }

    public List doTest(String url,Object param, int thrdCnt, int reqCnt) {
        lock = true;
        this.threadCount = thrdCnt > reqCnt ? reqCnt : thrdCnt; //小的为线程数
        this.requestCount = reqCnt;
        this.requestUrl = url;

        finishRequestCount.set(0);
        successRequestCount.set(0);
        finishRequestThreadCount.set(0);
        useTimeGather.clear();

        int avaCount = requestCount / threadCount;   //单线程需完成的请求数
        int num;
        long begin = System.nanoTime();
        log.info("任务开始");
        for (int i = 0; i < threadCount; i++) {
            if (threadCount - 1 == i) {
                num = avaCount + requestCount % threadCount; //最后一个线程负责结尾
                log.info("{}全部线程启动。耗时{}ms",threadCount,(Long.valueOf(System.nanoTime()) - begin) / 1000000l);
            } else {
                num = avaCount;
            }
            HttpExecutor executor = new HttpExecutor(requestUrl, param, num, (index, count, result, useTime) -> {
                finishRequestCount.incrementAndGet();
                if (result.indexOf("XCX") >= 0) {
                    successRequestCount.incrementAndGet();
                }
                useTimeList.add(useTime);
                //log.info("{}-线程完成：{}/{}",hashCode(),index,count);
                if (index == count) {// 该线程完成所有请求
                    int cnt = finishRequestThreadCount.incrementAndGet();
                    if (cnt == threadCount) {
                        lock = false;
                        finishAllUseTime  = (Long.valueOf(System.nanoTime()) - begin) / 1000000l;
                        log.info("{}线程请求{}次，总耗时" + finishAllUseTime + "ms",threadCount,requestCount);
                        successRate = String.valueOf(successRequestCount.doubleValue()/finishRequestCount.doubleValue() * 100) + "%";
                        log.info("成功率：{}",successRate);
                    }
                }
            });
            cachedThreadPool.execute(executor);
        }
        while (true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            log.info("发起{}请求，成功{}请求,qps-{},活跃线程{}",finishRequestCount,successRequestCount,finishRequestCount.intValue() - localRequestCount,((ThreadPoolExecutor)cachedThreadPool).getActiveCount());

            localRequestCount = finishRequestCount.intValue();
            if (finishRequestCount.intValue() >= reqCnt && finishAllUseTime != 0 && !successRate.equals("") ){return useTimeList;}

        }
    }

}
